(* Lexer specification *)
(* Your name:  LUONG VINH THAO        *)
(* Your id:  PUFMINF1209          *)

{
open Myparser
open Lexing
exception UnterminateString of string 
exception UnrecognizeEscapedChar of string 
exception UnrecognizeChar  of string 
exception UnterminateComment  of string
}
let letter= ['A'-'Z' 'a'-'z' '_']
let digit= ['0' - '9']
let decimal ='.'digit*
let exp= ['E' 'e']['+' '-']? digit+
(*---------------------------------------------------------------------------------*)
rule token = parse
| [' ' '\t' ] 	{ token lexbuf } (*skip blanks*)
| '\n'       	{ new_line lexbuf; token lexbuf }
|"bool" 										{BOOL}
|"break" 										{BREAK}
| "class" 									{CLASS}
| "continue" 								{CONTINUE}
| "do" 											{DO}
| "downto" 									{DOWNTO}
| "else" 										{ELSE}
| "extends" 								{EXTENDS}
| "float"										{FLOAT}
| "for" 										{FOR}
| "if" 											{IF}
| "integer" |"int"								{INTEGER}
| "new" 										{NEW}
| "repeat" 									{REPEAT}
| "string" 									{STRING}
| "then" 										{THEN}
| "to" 											{TO}
| "until" 									{UNTIL}
| "while"										{WHILE}
| "return" 									{RETURN}
| "void" 										{VOID}
| "null" 										{NULL}
| "self" 										{SELF}
| '+' 											{ADD}
| '-' 											{SUB}
| '*' 											{MUL}
| '/' 											{FDIVI}
| '\\'												{IDIVI}
| '%' 											{MOD}
| ":=" 											{ASSIG}
| "=="											{EQUAL}
| '='												{ONEQUAL}
| '<'										 		{LESS}
| '>'												{GREAT}
| "<=" 											{LEQUAL}
| ">=" 											{GEQUAL}
| "<>" 											{NEQUAL}
| "&&" 											{AND}
| '!' 											{NOT}
| "||" 											{OR}
| '^' 											{CONCAT}
| '[' 											{LSQUARE}
| ']' 											{RSQUARE}
| '{' 											{LPAREN}
| '}' 											{RPAREN}
| '(' 											{LBRACK}
| ')' 											{RBRACK}
| ';' 											{SEMICOLON}
| ':' 											{COLON}
| "::"											{DCOLON}
| '.' 											{DOT}
| ',' 											{COMMA}
| "true" 						as x				{BOOL_LITERAL (bool_of_string x)}
| "false" 					as x				{BOOL_LITERAL (bool_of_string x)}
|letter(letter|digit)*  as y		{ID y} (*identifier*)
|digit+ 	as x			{ INT_LITERAL	(int_of_string x )}
| digit+(decimal|exp|decimal exp) as x	{FLOAT_LITERAL (float_of_string x )}
| '#'[^ '\n']*  {token lexbuf} (* line comment*)
|  "(*" {blockcomment lexbuf}
| '"' {string_literal "" lexbuf} 
| eof	     	{ EOF }
| _       	{ raise (UnrecognizeChar (Lexing.lexeme lexbuf)) }

(*string*)
and string_literal y = parse 
|'\\'['b' 'f' 'r' 'n' 't' '"' '\\' ] as x {string_literal (y ^  x) lexbuf}
|'\\'_    { raise (UnrecognizeEscapedChar (Lexing.lexeme lexbuf)) }
| '\n'|  eof { raise (UnterminateString (Lexing.lexeme lexbuf)) }
|	'"' {STRING_LITERAL y}
|_ as x {string_literal (y ^ (Char.escaped x)) lexbuf}

(*Block comment*)

and blockcomment = parse 
| eof { raise (UnterminateComment (Lexing.lexeme lexbuf)) }
|	"*)" {token lexbuf}
|_ {blockcomment lexbuf}

